package com.tabjin.rfidsocket.service.sys.impl;

import com.google.common.base.Preconditions;
import com.mysql.fabric.xmlrpc.base.Param;
import com.tabjin.rfidsocket.common.RequestHolder;
import com.tabjin.rfidsocket.common.utils.BeanValidator;
import com.tabjin.rfidsocket.exception.ParamException;
import com.tabjin.rfidsocket.mapper.mapper.SysAclCustomMapper;
import com.tabjin.rfidsocket.mapper.mapper.SysAclMapper;
import com.tabjin.rfidsocket.mapper.mapper.SysAclModuleCustomMapper;
import com.tabjin.rfidsocket.mapper.mapper.SysAclModuleMapper;
import com.tabjin.rfidsocket.pojo.SysAclModule;
import com.tabjin.rfidsocket.pojo.bo.SysAclModuleBO;
import com.tabjin.rfidsocket.pojo.vo.SysAclModuleVO;
import com.tabjin.rfidsocket.service.sys.SysAclModuleService;
import com.tabjin.rfidsocket.utils.LevelUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @author tabjin
 * create at 2020/12/22 17:17
 * @program rfid_socket
 * @description
 */
@Service
public class SysAclModuleServiceImpl implements SysAclModuleService {

    static final Logger logger = LoggerFactory.getLogger(SysAclModuleServiceImpl.class);

    @Autowired
    private SysAclModuleMapper sysAclModuleMapper;

    @Autowired
    private SysAclModuleCustomMapper sysAclModuleCustomMapper;

    @Autowired
    private SysAclMapper sysAclMapper;

    @Autowired
    private SysAclCustomMapper sysAclCustomMapper;

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public SysAclModuleVO add(SysAclModuleBO sysAclModuleBO) {
        BeanValidator.check(sysAclModuleBO);
        if (checkExist(sysAclModuleBO.getParentId(), sysAclModuleBO.getName(), sysAclModuleBO.getId())) {// 存在
            logger.error("新增权限模块 同一级存在相同名称的权限模块");
            throw new ParamException("新增权限模块 同一级存在相同名称的权限模块");
        }

        // 组装权限模块类
        SysAclModule sysAclModule = SysAclModule.builder()
                .name(sysAclModuleBO.getName())
                .parentId(sysAclModuleBO.getParentId())
                .level(sysAclModuleBO.getLevel())
                .seq(sysAclModuleBO.getSeq())
                .status(sysAclModuleBO.getStatus())
                .remark(sysAclModuleBO.getRemark())
                .build();
        sysAclModule.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysAclModule.setOperateIp("127.0.0.1");
        sysAclModule.setOperateTime(new Date());

        sysAclModuleMapper.insertSelective(sysAclModule);

        SysAclModuleVO vo = new SysAclModuleVO();
        BeanUtils.copyProperties(sysAclModule, vo);
        return vo;
    }

    /**
     * 更新权限模块
     *
     * @param sysAclModuleBO 权限模块BO类
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void update(SysAclModuleBO sysAclModuleBO) {
        BeanValidator.check(sysAclModuleBO);
        if (checkExist(sysAclModuleBO.getParentId(), sysAclModuleBO.getName(), sysAclModuleBO.getId())) {// 存在
            logger.error("更新权限模块 同一级存在相同名称的权限模块");
            throw new ParamException("更新权限模块 同一级存在相同名称的权限模块");
        }

        SysAclModule before = sysAclModuleMapper.selectByPrimaryKey(sysAclModuleBO.getId());
        Preconditions.checkNotNull(before, "待更新的权限模块不存在");

        SysAclModule after = SysAclModule.builder()
                .id(sysAclModuleBO.getId())
                .name(sysAclModuleBO.getName())
                .parentId(sysAclModuleBO.getParentId())
                .seq(sysAclModuleBO.getSeq())
                .remark(sysAclModuleBO.getRemark())
                .build();
        after.setLevel(LevelUtil.calculateLevel(getLevel(sysAclModuleBO.getParentId()), sysAclModuleBO.getParentId()));
        after.setOperator(RequestHolder.getCurrentUser().getUsername());
        after.setOperateIp("127.0.0.1");
        after.setOperateTime(new Date());

        updateWithChild(before, after);
    }

    /**
     * 删除权限模块
     *
     * @param aclModuleId
     */
    @Override
    public void delete(Integer aclModuleId) {
        SysAclModule sysAclModule = sysAclModuleMapper.selectByPrimaryKey(aclModuleId);
        Preconditions.checkNotNull(sysAclModule, "待删除的权限模块不存在");

        // 是否有子权限模块和权限点
        if (sysAclModuleCustomMapper.countByParentId(aclModuleId) > 0) {
            throw new ParamException("待更新的权限模块有子权限模块，不可直接删除");
        }
        if (sysAclCustomMapper.countByAclModuleId(aclModuleId) > 0) {
            throw new ParamException("待更新的权限模块有权限点，不可直接删除");
        }

        sysAclModuleMapper.deleteByPrimaryKey(aclModuleId);
    }

    /**
     * 权限模块是有层级的，需要递归
     *
     * @param before 更新之前的权限模块信息
     * @param after  更新后的权限模块信息
     */
    @Transactional
    void updateWithChild(SysAclModule before, SysAclModule after) {
        // 子权限模块是否需要更新
        String newLevelPrefix = after.getLevel();
        String oldLevelPrefix = before.getLevel();
        if (!after.getLevel().equals(before.getLevel())) {// 不一致才需要进行子部门的更新
            // 当前部门的子权限模块
            List<SysAclModuleVO> sysAclModuleVOList = sysAclModuleCustomMapper.getChildSysAclModuleByLevel(before.getLevel());
            if (CollectionUtils.isNotEmpty(sysAclModuleVOList)) {// 子部门不为空
                for (SysAclModuleVO sysAclModuleVO : sysAclModuleVOList) {
                    String level = sysAclModuleVO.getLevel();// 当前部门的level
                    if (level.indexOf(oldLevelPrefix) == 0) {
                        level = newLevelPrefix + level.substring(oldLevelPrefix.length());
                        sysAclModuleVO.setLevel(level);
                    }
                }
                // 批量更新权限模块level
                sysAclModuleCustomMapper.batchUpdateLevel(sysAclModuleVOList);
            }
        }
        sysAclModuleMapper.updateByPrimaryKeySelective(after);
    }

    /**
     * 检验权限模块是否存在
     *
     * @param parentId
     * @param aclModuleName
     * @param aclModuleId
     * @return
     */
    private boolean checkExist(Integer parentId, String aclModuleName, Integer aclModuleId) {
        return sysAclModuleCustomMapper.countByNameAndParentId(parentId, aclModuleName, aclModuleId) > 0;
    }

    /**
     * 获取权限模块level
     *
     * @param aclModuleId 权限模块id
     * @return
     */
    private String getLevel(Integer aclModuleId) {
        SysAclModule aclModule = sysAclModuleMapper.selectByPrimaryKey(aclModuleId);
        if (aclModule == null) {
            return null;
        }
        return aclModule.getLevel();
    }
}
